﻿///////////////////////////////////////////////////////////////
//                                                           //
// Code from Arcanea Project.                                //
//                                                           //
// Please include this license part to every reproduction    //
//   of code.                                                //
//                                                           //
// This code is under Ms-RL license                          //
//                                                           //
// Please read futher information about the license,         //
//   the project (news and updates) and the                  //
//   contributors on the address :                           //
//     http://www.codeplex.com/Arcanea/                      //
//                                                           //
///////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using Arcanea.Mediator.Toolbox;
using Arcanea.Mediator.XmlClasses;
using System.Data.SqlClient;
using Arcanea.BaseEngine.Interfaces;
using Arcanea.BaseEngine.SqlServer;
using System.Reflection;
using log4net;

namespace Arcanea.BaseEngine.Generics
{

    /// <summary>
    /// Classe qui assure un pool de connection a une base.
    /// </summary>
    /// <typeparam name="BaseAccessType">Type qui definit l accesseur de la base</typeparam>
    public class PoolSwitcher<TBaseAccessType> where TBaseAccessType : IBaseAccess, new()
    {
        protected static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        List<IBaseAccess> freeConnection = null;
        string connectionString = "";

        /// <summary>
        /// Initialise le pool switcher.
        /// </summary>
        /// <param name="connectionString">String de connection a la base</param>
        /// <param name="nombreConnection">Nombre de connection dans le pool</param>
        /// <returns>true si tout va bien</returns>
        public bool Initialise(string connectionString, int nombreConnection)
        {
            freeConnection = new List<IBaseAccess>(nombreConnection);
            this.connectionString = connectionString;
            logger.Info("Poolswitcher initialisé avec " + connectionString + " avec des connections de type : " + typeof(TBaseAccessType).Name);

            return true;
        }

        /// <summary>
        /// Demande une connection au pool switcher.
        /// Si elle n existe pas, il la cree.
        /// Sans initialisation, le poolswitcher retourne une exception
        /// </summary>
        /// <returns>la connection demandee</returns>
        public IBaseAccess GetConnection()
        {
            if (freeConnection == null)
                throw new ArgumentException("Initialisez le poolswitcher avec la connectionString");

            IBaseAccess res = null;
            if (freeConnection.Count > 0)
            {
                res = freeConnection[0];
                freeConnection.RemoveAt(0);
                if (!res.IsOpenned())
                {
                    res = new TBaseAccessType();
                    res.Connection(connectionString);
                }
            }
            else
            {
                res = new TBaseAccessType();
                //Si la connection échoue, on laisse filer l'exception.
                res.Connection(connectionString);

                logger.Info("Ajout d'une connection au pool");
            }

            return res;
        }

        /// <summary>
        /// Libere et rends une connection au poolswitcher
        /// </summary>
        /// <param name="con">La connection qui n est plus utilisee</param>
        public void FreeConnection(IBaseAccess con)
        {
            if (freeConnection == null)
                throw new ArgumentException("Initialisez le poolswitcher avec la connectionString");


            if (con.IsOpenned())
            {
                freeConnection.Add(con);
            }
            else
            {
                logger.Info("Connection perdue dans le free ");
            }
        }

    }
}
